home *** CD-ROM | disk | FTP | other *** search
Wrap
/* File: CompositeClassDriver.c Contains: Core functionality to Composite Class Driver Version: xxx put version here xxx Copyright: © 1997-1998 by Apple Computer, Inc., all rights reserved. */ #include <Types.h> #include <Devices.h> #include <processes.h> #include <DriverServices.h> #include <USB.h> #include "CompositeClassDriver.h" extern usbCompositePBStruct myCompositePBRecord; void InitParamBlock(USBDeviceRef theDeviceRef, USBPB * paramblock) { paramblock->usbReference = theDeviceRef; paramblock->usbCompletion = (USBCompletion)CompositeDeviceCompletionProc; paramblock->pbLength = sizeof(usbCompositePBStruct); paramblock->pbVersion = kUSBCurrentPBVersion; paramblock->usbWIndex = 0; paramblock->usbBuffer = nil; paramblock->usbStatus = kUSBNoErr; paramblock->usbReqCount = 0; paramblock->usbActCount = 0; paramblock->usbWValue = 0; paramblock->usbFlags = 0; } Boolean immediateError(OSStatus err) { return((err != kUSBPending) && (err != kUSBNoErr) ); } void CompositeDeviceInitiateTransaction(USBPB *pb) { register usbCompositePBStruct *pCompositePB; OSStatus myErr; pCompositePB = (usbCompositePBStruct *)(pb); pCompositePB->transDepth++; if ((pCompositePB->transDepth < 0) || (pCompositePB->transDepth > 1)) { USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver: Illegal Transaction Depth", pCompositePB->pb.usbRefcon); } do { switch(pCompositePB->pb.usbRefcon & ~kRetryTransaction) { case kGetFullConfiguration0: InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb); pCompositePB->pb.usbWIndex = 0; /* First try configuration 0, if it doesn't succeed, then try config 1*/ pCompositePB->pb.usbRefcon |= kCompletionPending; pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc; myErr = USBGetFullConfigurationDescriptor(pb); if(immediateError(myErr)) { USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver: USBGetFullConfiguration (#0) - immediate error", myErr); } break; case kGetFullConfiguration1: InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb); pCompositePB->pb.usbWIndex = 1; /* Try configuration 1 (some devices seem to expect config 0, others config 1 */ pCompositePB->pb.usbRefcon |= kCompletionPending; pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc; myErr = USBGetFullConfigurationDescriptor(pb); if(immediateError(myErr)) { USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver: USBGetFullConfiguration (#1) - immediate error", myErr); } break; case kSetConfig: InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb); pCompositePB->pb.usbBMRequestType = USBMakeBMRequestType(kUSBOut, kUSBStandard, kUSBDevice); pCompositePB->pb.usbBRequest = kUSBRqSetConfig; pCompositePB->pb.usbWValue = pCompositePB->pFullConfigDescriptor->configValue; /* Use configuration ID value from descriptor */ pCompositePB->pb.usbRefcon |= kCompletionPending; pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc; myErr = USBDeviceRequest(pb); if(immediateError(myErr)) { USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver: kSetConfig - immediate error", myErr); } break; case kNewInterfaceRef: InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb); // Note: pCompositePB->usbWIndex will be set to zero by InitParamBlock // so set it again to pCompositePB->interfaceIndex before calling USBNewInterfaceRef pCompositePB->pb.usbWIndex = pCompositePB->interfaceIndex; pCompositePB->pb.usbRefcon |= kCompletionPending; pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc; myErr = USBNewInterfaceRef(pb); if(immediateError(myErr)) { USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver: kNewInterfaceRef - immediate error", myErr); } break; default: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver - Transaction initiated with bad refcon value", pCompositePB->pb.usbRefcon); pCompositePB->pb.usbRefcon = kUndefined + kExitDriver; break; } } while (false); // At this point the control is returned to the system. If a USB transaction // has been initiated, then it will call the Complete procs // (below) to handle the results of the transaction. } void CompositeDeviceCompletionProc(USBPB *pb) { OSStatus myErr; register usbCompositePBStruct *pCompositePB; USBInterfaceDescriptorPtr pInterfaceDescriptor; UInt32 i; pCompositePB = (usbCompositePBStruct *)(pb); pCompositePB->transDepth--; if ((pCompositePB->transDepth < 0) || (pCompositePB->transDepth > 1)) { USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver - Illegal Transaction Depth", pCompositePB->transDepth); } if((pCompositePB->pb.usbStatus != kUSBNoErr) && (pCompositePB->pb.usbStatus != kUSBPending)) { USBExpertStatus(pCompositePB->pb.usbReference, "\pComposite Driver: Completion Error", pCompositePB->pb.usbStatus); pCompositePB->pb.usbRefcon &= ~(kCompletionPending + kExitDriver); pCompositePB->pb.usbRefcon |= kRetryTransaction; pCompositePB->retryCount--; if (!pCompositePB->retryCount) { if (pCompositePB->pb.usbRefcon == kGetFullConfiguration1) { pCompositePB->pb.usbRefcon = kGetFullConfiguration0; } else { USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver: Too many retries", pCompositePB->pb.usbRefcon); pCompositePB->pb.usbRefcon = kExitDriver; return; } } } else { pCompositePB->pb.usbRefcon &= ~kRetryTransaction; pCompositePB->retryCount = kCompositeRetryCount; } if (pCompositePB->pb.usbRefcon & kCompletionPending) { pCompositePB->pb.usbRefcon &= ~(kCompletionPending + kExitDriver); switch(pCompositePB->pb.usbRefcon) { case kGetFullConfiguration0: case kGetFullConfiguration1: // DebugStr("\pCheck power"); pCompositePB->pFullConfigDescriptor = pCompositePB->pb.usbBuffer; if (pCompositePB->pFullConfigDescriptor == nil) { USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver: USBGetFullConfiguration - pointer is nil", pCompositePB->pb.usbRefcon); pCompositePB->pb.usbRefcon = kExitDriver; break; } BlockCopy( (void *)pCompositePB->pFullConfigDescriptor, (void *)(&(pCompositePB->partialConfigDescriptor)), (Size)(sizeof(USBConfigurationDescriptor) ) ); if (pCompositePB->pFullConfigDescriptor->maxPower <= pCompositePB->busPowerAvailable) { pCompositePB->pb.usbRefcon = kSetConfig; } else { USBExpertSetDevicePowerStatus(pCompositePB->pb.usbReference, 0, 0, kUSBDevicePower_BusPowerInsufficient, pCompositePB->busPowerAvailable, pCompositePB->pFullConfigDescriptor->maxPower); USBExpertFatalError(pCompositePB->pb.usbReference, kUSBDevicePowerProblem, "\pComposite Driver - Insufficient power for device", pCompositePB->pb.usbRefcon); pCompositePB->pb.usbRefcon = kExitDriver; } break; case kSetConfig: /* get all the interface descriptors and save them */ for (i=0; i < pCompositePB->partialConfigDescriptor.numInterfaces; i++) { pCompositePB->interfaceRefArray[i] = 0; myErr = GetInterfaceDescriptor(pCompositePB->pFullConfigDescriptor, (UInt32)i, &pInterfaceDescriptor); if (kUSBNoErr == myErr) { BlockCopy((void *)pInterfaceDescriptor, (void *)(&(pCompositePB->interfaceDescriptors[i])), (Size)(pInterfaceDescriptor->length)); } else /* if GetInterfaceDescriptor returned an error, then set the length to zero (so we know later) */ { pCompositePB->interfaceDescriptors[i].length = 0; } } pCompositePB->interfaceIndex = 0; pCompositePB->interfaceCount = pCompositePB->partialConfigDescriptor.numInterfaces; pCompositePB->pb.usbRefcon = kNewInterfaceRef; break; case kNewInterfaceRef: /* save the new interface ref for this interface */ pCompositePB->interfaceRefArray[pCompositePB->interfaceIndex] = pCompositePB->pb.usbReference; /* only install the interface driver if we had a valid interface descriptor */ if (pCompositePB->interfaceDescriptors[pCompositePB->interfaceIndex].length != 0) { USBExpertInstallInterfaceDriver(pCompositePB->interfaceRefArray[pCompositePB->interfaceIndex], &pCompositePB->deviceDescriptor, &pCompositePB->interfaceDescriptors[pCompositePB->interfaceIndex], pCompositePB->deviceRef, 0); } /* advance to the next interface */ pCompositePB->interfaceIndex++; /* if there's more interfaces, then just keep cycling through kNewInterfaceRef */ if (pCompositePB->interfaceIndex < pCompositePB->interfaceCount) { pCompositePB->pb.usbRefcon = kNewInterfaceRef; } else { pCompositePB->pb.usbRefcon = kExitDriver; } break; default: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver - Transaction completed with a bad refcon value", pCompositePB->pb.usbRefcon); pCompositePB->pb.usbRefcon = kExitDriver; break; } } if (!(pCompositePB->pb.usbRefcon & kExitDriver)) CompositeDeviceInitiateTransaction(pb); pCompositePB->okayToFinalizeFlag = true; pCompositePB->disposeCompletedFlag = true; }